﻿/* 
 * Shuriken is the legal property of its developers. Please refer to the
 * COPYRIGHT file distributed with this
 * source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Shuriken.Base;


namespace Shuriken.Core.Store
{
    public class QNModule : IModule 
    {
        private Assembly m_ModuleAssembly;
        private string m_ModuleName;
        private System.Resources.ResourceManager m_ResourceManager; 

        public QNModule(Assembly asm)
        {
            System.Diagnostics.Trace.Assert(asm != null, "Null module is not allowed in QNModule's constructor!");
            m_ModuleAssembly = asm;
            m_ModuleName = asm.ManifestModule.Name.Replace(".dll", string.Empty);
            string resourceName = m_ModuleName + ".Properties.Resources";
            m_ResourceManager = new System.Resources.ResourceManager(resourceName, m_ModuleAssembly);
        }

        public void Init()
        {
            Type[] types = ImplementedTypeList();

            if (types == null || types.Length == 0)
            {
                return; 
            }

            foreach (Type t in types)
            {
                // Check if it is a scanner
                if (IsInterfaceImplemented(t, typeof(IScanner)))
                {
                    // Here we are going to add the scanner from the module.
                    RegisterScanner(t);
                }

                // Check if it is a subject 
                if (IsInterfaceImplemented(t, typeof(ISubject)))
                {
                    RegisterSubject(t);
                }

                // Check if it is an action 
                if (IsInterfaceImplemented(t, typeof(IAction)))
                {
                    // Adding action registration 
                    RegisterAction(t);
                }
            }
        }

        private void RegisterAction(Type action_type)
        {
            ConstructorInfo[] constructors = action_type.GetConstructors();

            if (constructors.Length > 0)
            {
                Object obj = constructors[0].Invoke(new Object[0]);
                IAction action = (IAction)obj;
                QNAction qnAction = new QNAction(action);

                PluginActionManager.DefaultInstance.AddAction(qnAction);
            }
        }

        private void RegisterScanner(Type scanner_type)
        {
            ConstructorInfo[] constructors = scanner_type.GetConstructors();

            if (constructors.Length > 0)
            {
                Object obj = constructors[0].Invoke(new Object[0]);
                IScanner scanner = (IScanner)obj;

                // Construct the new store and register it with the store manager 
                QNStore store = new QNStore("Plugin", scanner.Name, true, new QNScanner(scanner));
                store.UpdateStore();

                StoreManager.GetDefaultInstance().StoreList.Add(store);
            }
        }

        /// <summary>
        /// Registers an individual subject 
        /// </summary>
        /// <param name="subject_type"></param>
        private void RegisterSubject(Type subject_type)
        {
            ConstructorInfo[] constructors = subject_type.GetConstructors();

            if (constructors.Length > 0)
            {
                Object obj = constructors[0].Invoke(new Object[0]);
                ISubject subj = (ISubject)obj;

                QNStoreItem qnSubject = new QNStoreItem(subj);
                TryRegisterIcon(qnSubject); 
                StoreManager.GetDefaultInstance().AddSubject(qnSubject);

                qnSubject.RegisterActions();
            }
        }

        private void TryRegisterIcon(QNStoreItem qnSubject)
        {
            string subjIcon = qnSubject.Icon; 
            string defaultIcon = ImageStore.GetDefaultSubjectImage();

            if(String.IsNullOrEmpty(subjIcon))
            {
                qnSubject.Icon = defaultIcon;
                return; 
            }
            
            // attempt to load the icon for the module 
            object obj = m_ResourceManager.GetObject(subjIcon);

            if (obj == null)
            {
                qnSubject.Icon = defaultIcon;
                return; 
            }

            try
            {
                System.Drawing.Icon icon = (System.Drawing.Icon)obj;
                string imgKey = ImageStore.AddResourceImage(icon);
                qnSubject.Icon = imgKey;
            }
            catch (System.InvalidCastException excp)
            {
                string msg = ApplicationEnvironment.Diagnostics.FormatException(excp);
                Shuriken.Core.Utils.Tracer.WriteError(msg, "Unexpected Error");
                qnSubject.Icon = defaultIcon;
                return; 
            }

            //object obj = ResourceManager.GetObject("shuriken_application_icon", resourceCulture);
         //   ImageStore.AddResourceImage(
        }

        private bool IsInterfaceImplemented(Type t, Type iface)
        {
            foreach (Type i in t.GetInterfaces())
            {
                if (iface.Equals(i))
                {
                    return true; 
                }
            }

            return false; 
        }

        #region IModule Members

        public Type[] ImplementedTypeList()
        {
            string scanner = typeof(IScanner).Name;
            string action = typeof(IAction).Name;

            return m_ModuleAssembly.GetExportedTypes();
        }

        #endregion

        #region IObject Members

        public string Name
        {
            get { return string.Empty; }
        }

        public string Description
        {
            get { return string.Empty; }
        }

        public string Icon
        {
            get
            {
                return string.Empty;
            }

            set { }
        }

        #endregion
    }
}
